(function () {

    const f = i => i < 10 ? '0' + i : i
    const f3 = i => i >= 100 ? i : i >= 10 ? "0" + i : "00" + i

    Date.prototype.oldToString = Date.prototype.toString

    /** 格式化成yyyy-MM-dd HH:mm:ss格式返回 */
    Date.prototype.toString = function () {
        return `${this.getFullYear()}-${f(this.getMonth() + 1)}-${f(this.getDate())} ${f(this.getHours())}:${f(this.getMinutes())}:${f(this.getSeconds())}`
    }

    Date.prototype.toJSON = Date.prototype.toString

    /** 日期时间格式化
     * @param fmt 有效格式: yyyy/yy: 4/2位年份, MM/M: 月份, dd/d: 日期, HH/H: 小时, mm/m: 分钟, ss/s: 秒, SSS/S: 毫秒
     */
    Date.prototype.format = function (fmt) {
        if (!fmt) return this.toString()
        const ff = s => {
            switch (s) {
                case 'yy':   return this.getFullYear() % 100
                case 'yyyy': return this.getFullYear()
                case 'MM':   return f(this.getMonth() + 1)
                case 'M':    return this.getMonth() + 1
                case 'dd':   return f(this.getDate())
                case 'd':    return this.getDate()
                case 'HH':   return f(this.getHours())
                case 'H':    return this.getHours()
                case 'mm':   return f(this.getMinutes())
                case 'm':    return this.getMinutes()
                case 'ss':   return f(this.getSeconds())
                case 's':    return this.getSeconds()
                case 'SSS':  return f3(this.getMilliseconds())
                case "S":    return this.getMilliseconds()
                default: return s
            }
        }
        return fmt.replace(/(y+|M+|d+|H+|m+|s+)/g, s => ff(s))
    }

    //Usage: "{} love {}.".format("I","you"); //output: I love you.
    const fmtPat = /\{\}/g;
    String.prototype.format = function () {
        const args = arguments;
        let idx = 0;
        return this.replace(fmtPat, m => args[idx++]);
    }

    window.apiCall = async function (url, option) {
        const resp = await fetch(url, option)
        const respText = await resp.text()
        const ret = {
            status: resp.status,
            statusText: resp.statusText,
            headers: resp.headers,
            text: respText,
        }
        if (resp.headers.get('Content-Type') == 'application/json')
            ret.json = JSON.parse(respText)
        return ret
    }

    window.apiGet = async function (url, urlParams, token) {
        const headers = token ? {'Authorization': 'Bearer ' + token} : null
        if (urlParams) {
            const ps = []
            for (const k in urlParams)
                if (urlParams[k] !== "")
                    ps.push(k + '=' + encodeURIComponent(urlParams[k]))
            url += '?' + ps.join('&')
        }
        return apiCall(url, {headers})
    }
    
    window.apiPost = async function (url, body, token) {
        const headers = {'Content-Type': 'application/json'}
        if (token) headers['Authorization'] = 'Bearer ' + token
        if (body) body = JSON.stringify(body)
        return apiCall(url, {headers, body, method: 'POST'})
    }

})()